/**
 *
 * The MIT License
 *
 * Copyright (c) 2008 Board of Trustees, Leland Stanford Jr. University. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.macdadi.multi.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import org.macdadi.core.client.auth.AuthService;
import org.macdadi.core.client.auth.AuthenticatedUser;
import org.macdadi.core.client.auth.AuthenticationControl;
import org.macdadi.core.client.auth.AuthorizationException;
import org.macdadi.core.client.domain.DataService;
import org.macdadi.core.client.domain.ExtendedProjectInfo;
import org.macdadi.multi.client.components.*;

/**
 * @author Ben Suter <ben.suter@gmail.com>
 */
public class Overview implements EntryPoint, AuthenticationControl.AuthenticationListener, HistoryListener, FilteredProjectListing
{
    private static final Images images = (Images) GWT.create(Images.class);
    protected DockPanel panel;
    protected AuthenticationControl authControl;
    protected ProjectListing projectListing;
    protected ProjectListingControls projectListingControls;
    protected WidgetDialog searchProjectsDialog;
    protected static AuthenticatedUser currentUser;

    public interface Images extends ImageBundle
    {
        AbstractImagePrototype logoRight();
    }

    public void onModuleLoad()
    {
        /* Allow users to log in and out, and respond
         * to these changes by adjusting the UI accordingly.
         */
        authControl = new AuthenticationControl();
        authControl.setListener(this);

        buildUI();

        /* Listen for history changes. Each history token
         * corresponds to a particular filter setting applied
         * to the ProjectListing.
         */
        History.addHistoryListener(this);

        /* Unless otherwise specified, start with listing of all projects */
        String initToken = History.getToken();
        if (initToken.length() == 0) {
            History.newItem("all");
        } else {
            onHistoryChanged(initToken);
        }
    }

    public void buildUI()
    {
        panel = new DockPanel();
        panel.setVerticalAlignment(HasAlignment.ALIGN_TOP);
        panel.setSpacing(20);
        panel.setHeight("100%");
        panel.setStyleName("macdadi-Overview");

        /* The top panel displays a title and the login/logout links */
        HorizontalPanel top = new HorizontalPanel();
        top.setWidth("100%");
        Widget title = new HTML("<h2>Welcome to MACDADI</h2>");
        top.add(title);
        top.setCellHorizontalAlignment(title, HasAlignment.ALIGN_LEFT);
        top.add(authControl);
        top.setCellHorizontalAlignment(authControl, HasAlignment.ALIGN_RIGHT);

        /* The center panel is the main content.
         * It expands to the available width of the page.
         */
        VerticalPanel center = new VerticalPanel();
        center.setWidth("100%");
        center.setVerticalAlignment(HasAlignment.ALIGN_TOP);
        center.add(top);
        projectListingControls = new ProjectListingControls();
        if ( getCurrentUser() == null ) {
            projectListingControls.setEnabledCreateNew(false);
            projectListingControls.setEnabledYours(false);
        }
        center.add(projectListingControls);
        projectListing = new ProjectListing();
        center.add(projectListing);
        panel.add(center, DockPanel.CENTER);

        /* The right side panel has a fixed width and arranges auxiliary
         * elements vertically, right-aligned: logo, sign-up, news
         */
        VerticalPanel rightSide = new VerticalPanel();
        rightSide.setVerticalAlignment(HasAlignment.ALIGN_TOP);
        rightSide.setStyleName("macdadi-RightSide");
        Widget logo = images.logoRight().createImage();
        // TODO: add some cute interaction to the logo
        rightSide.add(logo);
        rightSide.setCellHorizontalAlignment(logo, HasAlignment.ALIGN_RIGHT);
        rightSide.add(new CreateAccountPanel());
        rightSide.add(new NewsPanel());
        panel.add(rightSide, DockPanel.EAST);
        panel.setCellHorizontalAlignment(rightSide, HasAlignment.ALIGN_RIGHT);

        searchProjectsDialog = new WidgetDialog(new SearchProjectsPanel(this), "Please enter search terms");

        RootPanel.get().add(panel);
    }

    /**
     * Respond to changes in the history token, either in response to the user
     * clicking the back or forward browser buttons, or in response to
     * internal-hyperlink-induced state changes.
     *
     * @param historyToken the token representing the current history state
     */
    public void onHistoryChanged(String historyToken)
    {
        if ( "all".equals(historyToken) ) {
            listProjects(null, false, false);
        } else if ( "recent".equals(historyToken) ) {
            listProjects(null, true, false);
        } else if ( "yours".equals(historyToken) ) {
            listProjects(null, false, true);
        } else if ( "search".equals(historyToken) ) {
            searchProjectsDialog.show(projectListingControls.getAbsoluteLeft() + 20, projectListingControls.getAbsoluteTop() + 20);
        } else {
            /* An unknown history token was encountered, instead we show all projects.
             * Note that this handles login and logout clicks as well.
             */
            History.newItem("all");
        }
    }

    public void listProjects(String[] keywords, boolean recentOnly, boolean membershipOnly)
    {
        //GWT.log("Overview.listProjects", null);
        
        DataService.App.getInstance().listProjects(keywords, recentOnly, membershipOnly, getCurrentAuthToken(), new AsyncCallback()
        {
            public void onFailure(Throwable caught)
            {
                GWT.log("Failed to populate the projects table", caught);
                if (caught instanceof AuthorizationException) {
                    projectListingControls.setMessage("Please login to view projects");
                }
            }

            public void onSuccess(Object result)
            {
                ExtendedProjectInfo[] projects = (ExtendedProjectInfo[]) result;
                projectListing.displayProjects(projects);
                
                String msg;
                int numProjects = projects.length;
                if ( numProjects == 0 )
                    msg = "There are no matching projects";
                else if (  numProjects == 1 )
                    msg = "Showing one matching project";
                else
                    msg = "Showing " + numProjects + " projects";

                projectListingControls.setMessage(msg);
            }
        });
    }

    public void userAuthenticated(AuthenticatedUser user)
    {
        currentUser = user;
        projectListingControls.setEnabledCreateNew(true);
        projectListingControls.setEnabledYours(true);
    }

    public void userLoggedOut()
    {
        currentUser = null;
        projectListingControls.setEnabledCreateNew(false);
        projectListingControls.setEnabledYours(false);
    }

    public static AuthenticatedUser getCurrentUser() {
        return currentUser;
    }

    public static String getCurrentAuthToken() {
        if ( currentUser == null )
            return null;
        else
            return currentUser.getAuthToken();
    }

    public static void checkOperationAuthorized(String target, String operation, AsyncCallback callback) {
        AuthService.App.getInstance().isAuthorizedOperation(getCurrentAuthToken(), -1, target, operation, callback);    
    }

}
